﻿using Kylin.Wiki.Core.Enum;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Kylin.Wiki.Repository
{
    public interface IRepository<T> where T : class, new()
    { 

        #region 简单查询
        /// <summary>
        /// 按ID查询
        /// </summary>
        /// <param name="objId">实体ID</param>
        /// <returns></returns>
        T FindFirst(Expression<Func<T, bool>> where);

        /// <summary>
        /// 异步按条件查询
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<T> FindFirstAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 根据条件查询数据是否存在
        /// </summary>
        /// <param name="where">条件表达式树</param>
        /// <returns></returns>
        bool Exists(Expression<Func<T, bool>> where);

        /// <summary>
        /// 异步根据条件查询数据是否存在
        /// </summary>
        /// <param name="where">条件表达式树</param>
        /// <returns></returns>
        Task<bool> ExistsAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 通过条件查询数据
        /// </summary>
        /// <param name="objIds"></param>
        /// <returns></returns>
        List<T> Find(Expression<Func<T, bool>> where); 

        /// <summary>
        /// 异步通过条件查询数据
        /// </summary>
        /// <param name="objIds"></param>
        /// <returns></returns>
        Task<List<T>> FindAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 通过条件查询数据
        /// </summary>
        /// <param name="predicate">where条件</param>
        /// <param name="orderBy">排序字段,数据格式如:
        ///  orderBy = x => new Dictionary<object, bool>() {
        ///          { x.BalconyName,QueryOrderBy.Asc},
        ///          { x.TranCorpCode1,QueryOrderBy.Desc}
        ///         };
        /// </param>
        /// <returns></returns> 
        IQueryable<T> FindAsIQueryable(Expression<Func<T, bool>> predicate, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBy = null);

        /// <summary>
        /// 通过条件查询数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBy"></param>
        /// <returns></returns>
        Task<List<T>> Find(Expression<Func<T, bool>> predicate, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBy = null);

        /// <summary>
        /// 通过条件查询数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="predicate">查询条件</param>
        /// <param name="selector">返回类型如:Find(x => x.UserName == loginInfo.userName, p => new { uname = p.UserName });</param>
        /// <returns></returns>
        List<T> Find<TReulst>(Expression<Func<T, bool>> predicate, Expression<Func<T, T>> selector);

        /// <summary>
        /// 异步通过条件查询数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="predicate">查询条件</param>
        /// <param name="selector">返回类型如:Find(x => x.UserName == loginInfo.userName, p => new { uname = p.UserName });</param>
        /// <returns></returns>
        Task<List<T>> FindAsync<TReulst>(Expression<Func<T, bool>> predicate, Expression<Func<T, T>> selector);
        
        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="pageIndex">当前页</param>
        /// <param name="pagesize">页面大小</param>
        /// <param name="rowcount">数据总数</param>
        /// <param name="predicate">查询条件</param>
        /// <param name="orderBy"></param>
        /// <param name="returnRowCount"></param>
        /// <returns></returns>
        List<T> QueryablePage(int pageIndex, int pagesize, out int rowcount, Expression<Func<T, bool>> predicate, Dictionary<string, QueryOrderBy> orderBy, bool returnRowCount = true);

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pagesize"></param>
        /// <param name="rowcount"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBySelector"></param>
        /// <param name="selectorResult"></param>
        /// <param name="returnRowCount"></param>
        /// <returns></returns>
        List<T> QueryByPage<TResult>(int pageIndex, int pagesize, out int rowcount, Expression<Func<T, bool>> predicate, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBySelector, Expression<Func<T, T>> selectorResult, bool returnRowCount = true);

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pagesize"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBy"></param>
        /// <param name="selectorResult"></param>
        /// <returns></returns>
        List<T> QueryByPage<TResult>(int pageIndex, int pagesize, Expression<Func<T, bool>> predicate, Expression<Func<T, Dictionary<object, QueryOrderBy>>> orderBy, Expression<Func<T, T>> selectorResult = null);


        #endregion

        #region 添加操作
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="SaveChanges"></param>
        int Add(T entities, bool SaveChanges = false);

        /// <summary>
        /// 批量添加
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="SaveChanges"></param>
        int AddRange(IEnumerable<T> entities, bool SaveChanges = false);   
        #endregion

        #region 删除操作 

        /// <summary>
        /// 按Entity删除数据
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        int Delete(T model, bool saveChanges = false); 

        #endregion

        #region 修改操作

        /// <summary>
        /// 根据Entity修改数据（注意会修改所有字段值）
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        int Update(T entity, bool saveChanges = false);

        /// <summary>
        /// 根据Entity修改数据（指定字段）
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="updatedProperties"></param>
        /// <param name="saveChanges"></param>
        /// <returns></returns>
        int Update(T entity, Expression<Func<T, object>>[] updatedProperties, bool saveChanges = false);

        /// <summary>
        /// 批量修改数据（注意会修改所有字段值）
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        int Update(List<T> entities, bool saveChanges = false); 

        #endregion
         
    }
}
